package service.impl;

import java.util.*;

import mapper.LeaveApplyMapper;

import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import po.LeaveApply;
import service.LeaveService;

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 5)
@Service
public class LeaveServiceImpl implements LeaveService {

    @Autowired
    private LeaveApplyMapper leaveMapper;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;

    public ProcessInstance startWorkflow(LeaveApply apply, String userId) {

        // 保存请假信息
        apply.setApply_time(new Date().toString());
        apply.setUser_id(userId);
        leaveMapper.save(apply);

        // 使用请假申请表的主键作为businessKey,连接业务数据和流程数据
        String businessKey = String.valueOf(apply.getId());

        // 设置开启流程的当前用户
        identityService.setAuthenticatedUserId(userId);

        // 开启流程实例
        Map<String, Object> variables = new HashMap<>();
        variables.put("applyuserid", userId);
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("leave", businessKey, variables);
        String instanceId = instance.getId();

        System.out.println("流程启动成功");
        System.out.println("业务KEY=" + businessKey);
        System.out.println("流程ID=" + instanceId);

        // 补充流程实例ID
        apply.setProcess_instance_id(instanceId);
        leaveMapper.update(apply);

        return instance;
    }

    public List<LeaveApply> getDeptTaskPage(String userId, int firstRow, int rowCount) {
        List<LeaveApply> results = new ArrayList<>();
        // 查询任务列表 - 角色为部门经理的
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("部门经理").listPage(firstRow, rowCount);
        // List<Task> tasks = taskService.createTaskQuery().taskNameIn(Arrays.asList(new String[]{"部门领导审批", "人事审批"})).list();
        for (Task task : tasks) {
            String instanceId = task.getProcessInstanceId();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
            String businessKey = processInstance.getBusinessKey();
            LeaveApply leaveApply = leaveMapper.get(Integer.parseInt(businessKey));
            leaveApply.setTask(task);
            results.add(leaveApply);
        }
        return results;
    }

    public int getDeptTaskCount(String userId) {
        // 查询部门经理任务总数
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("部门经理").list();
        return tasks.size();
    }

    public LeaveApply getLeaveApply(int id) {
        LeaveApply leave = leaveMapper.get(id);
        return leave;
    }

    public List<LeaveApply> selectHrTaskPage(String userId, int firstRow, int rowCount) {
        List<LeaveApply> results = new ArrayList<LeaveApply>();
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("人事").listPage(firstRow, rowCount);
        for (Task task : tasks) {
            String instanceId = task.getProcessInstanceId();
            ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
            String businessKey = ins.getBusinessKey();
            LeaveApply a = leaveMapper.get(Integer.parseInt(businessKey));
            a.setTask(task);
            results.add(a);
        }
        return results;
    }

    public int selectHrTaskTotal(String userid) {
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("人事").list();
        return tasks.size();
    }

    public List<LeaveApply> getReportBackTaskList(String userId, int firstRow, int rowCount) {
        List<LeaveApply> results = new ArrayList<>();
        // 获取销假任务
        List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(userId).taskName("销假").listPage(firstRow, rowCount);
        for (Task task : tasks) {
            String instanceId = task.getProcessInstanceId();
            ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
            String businessKey = ins.getBusinessKey();
            // 分别获取申请信息
            LeaveApply leaveApply = leaveMapper.get(Integer.parseInt(businessKey));
            leaveApply.setTask(task);
            results.add(leaveApply);
        }
        return results;
    }

    public int getReportBackTaskCount(String userId) {
        List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(userId).taskName("销假").list();
        return tasks.size();
    }

    public List<LeaveApply> getpageupdateapplytask(String userid, int firstrow, int rowcount) {
        List<LeaveApply> results = new ArrayList<LeaveApply>();
        List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(userid).taskName("调整申请").listPage(firstrow, rowcount);
        for (Task task : tasks) {
            String instanceid = task.getProcessInstanceId();
            ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceid).singleResult();
            String businesskey = ins.getBusinessKey();
            LeaveApply a = leaveMapper.get(Integer.parseInt(businesskey));
            a.setTask(task);
            results.add(a);
        }
        return results;
    }

    public int getallupdateapplytask(String userid) {
        List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(userid).taskName("调整申请").list();
        return tasks.size();
    }

    public void completeReportBack(String taskId, String realStartTime, String realEndTime) {

        // 先签收
        taskService.complete(taskId);

        // 查询任务
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String instanceId = task.getProcessInstanceId();

        // 查询流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
        String businessKey = processInstance.getBusinessKey();

        // 查询申请信息
        LeaveApply leaveApply = leaveMapper.get(Integer.parseInt(businessKey));
        leaveApply.setReality_start_time(realStartTime);
        leaveApply.setReality_end_time(realEndTime);

        // 保存
        leaveMapper.update(leaveApply);
    }

    public void updatecomplete(String taskid, LeaveApply leave, String reapply) {
        Task task = taskService.createTaskQuery().taskId(taskid).singleResult();
        String instanceid = task.getProcessInstanceId();
        ProcessInstance ins = runtimeService.createProcessInstanceQuery().processInstanceId(instanceid).singleResult();
        String businesskey = ins.getBusinessKey();
        LeaveApply a = leaveMapper.get(Integer.parseInt(businesskey));
        a.setLeave_type(leave.getLeave_type());
        a.setStart_time(leave.getStart_time());
        a.setEnd_time(leave.getEnd_time());
        a.setReason(leave.getReason());
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("reapply", reapply);
        if (reapply.equals("true")) {
            leaveMapper.update(a);
            taskService.complete(taskid, variables);
        } else
            taskService.complete(taskid, variables);
    }

    public List<String> getHighLightedFlows(
            ProcessDefinitionEntity processDefinitionEntity,
            List<HistoricActivityInstance> historicActivityInstances) {

        List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId
        for (int i = 0; i < historicActivityInstances.size(); i++) {// 对历史流程节点进行遍历
            ActivityImpl activityImpl = processDefinitionEntity
                    .findActivity(historicActivityInstances.get(i)
                            .getActivityId());// 得 到节点定义的详细信息
            List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();// 用以保存后需开始时间相同的节点
            if ((i + 1) >= historicActivityInstances.size()) {
                break;
            }
            ActivityImpl sameActivityImpl1 = processDefinitionEntity
                    .findActivity(historicActivityInstances.get(i + 1)
                            .getActivityId());// 将后面第一个节点放在时间相同节点的集合里
            sameStartTimeNodes.add(sameActivityImpl1);
            for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
                HistoricActivityInstance activityImpl1 = historicActivityInstances
                        .get(j);// 后续第一个节点
                HistoricActivityInstance activityImpl2 = historicActivityInstances
                        .get(j + 1);// 后续第二个节点
                if (activityImpl1.getStartTime().equals(
                        activityImpl2.getStartTime())) {// 如果第一个节点和第二个节点开始时间相同保存
                    ActivityImpl sameActivityImpl2 = processDefinitionEntity
                            .findActivity(activityImpl2.getActivityId());
                    sameStartTimeNodes.add(sameActivityImpl2);
                } else {// 有不相同跳出循环
                    break;
                }
            }
            List<PvmTransition> pvmTransitions = activityImpl
                    .getOutgoingTransitions();// 取出节点的所有出去的线
            for (PvmTransition pvmTransition : pvmTransitions) {// 对所有的线进行遍历
                ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition
                        .getDestination();// 如果取出的线的目标节点存在时间相同的节点里，保存该线的id，进行高亮显示
                if (sameStartTimeNodes.contains(pvmActivityImpl)) {
                    highFlows.add(pvmTransition.getId());
                }
            }
        }
        return highFlows;
    }
}
